home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / boot / netBoot.new / dev / xd.c < prev    next >
C/C++ Source or Header  |  1990-12-19  |  8KB  |  347 lines

  1.  
  2. #ifndef lint
  3. /* static    char sccsid[] = "@(#)xd.c 1.0 86/03/12 Copyr 1986 Sun Micro";*/
  4. #endif
  5.  
  6. /*
  7.  * Copyright (c) 1986 by Sun Microsystems, Inc.
  8.  */
  9.  
  10. /* Standalone driver for Xylogics 751 */
  11.  
  12.  
  13. #ifndef M25
  14. #include "../dev/saio.h"
  15. #include "../h/param.h"
  16. #include "../dev/dkbad.h"
  17. #include "../dev/dklabel.h"
  18. #include "../dev/dkio.h"
  19. #include "../h/fsdir.h"
  20. #include "../dev/xdcreg.h"
  21. #include "../dev/xdreg.h"
  22.  
  23. extern char    msg_nolabel[];
  24.  
  25. struct xdparam {
  26.     unsigned short    xd_boff;    /* Cyl # starting partition */
  27.      unsigned short    xd_nsect;    /* Sect/track */
  28.      unsigned short    xd_ncyl;    /* Cyl/disk */
  29.      unsigned short    xd_nhead;    /* Heads/cyl */
  30.      unsigned short    xd_bhead;    /* Base head # for removable disk */
  31.      unsigned short    xd_drive;    /* Xylogics drive type ID */
  32.     int    xd_nblk;
  33.     int    xd_badaddr;        /* Disk block # of bad-block table */
  34.     struct dkbad xd_bad;
  35.     unsigned char    xd_unit;
  36. };
  37.  
  38. #define CYL(p)  (p*xdp->xd_nsect*xdp->xd_nhead)     /* cyl to block conv */
  39.  
  40. #define NSTD     2
  41. #define TIMEOUT    0x2ffff
  42. unsigned long xdstd[NSTD] = { 0xee80, 0xee88 };
  43.  
  44. /*
  45.  * Structure of our DMA area
  46.  */
  47. #define MAXBSIZE        8192
  48. struct xddma {
  49.     struct xdiopb    xdiopb;
  50.     char        xdblock[MAXBSIZE];    /* R/W data */
  51. };
  52.  
  53. /*
  54.  * What resources we need to run
  55.  */
  56. struct devinfo xdinfo = {
  57.     sizeof (struct xddevice), 
  58.     sizeof (struct xddma),
  59.     sizeof (struct xdparam),
  60.     NSTD,
  61.     xdstd,
  62.     MAP_MBIO,
  63. #ifdef BOOTBLOCK
  64.     DEV_BSIZE,
  65. #else
  66.     DEV_BSIZE,    /* MAXBSIZE, */
  67. #endif
  68. };
  69.  
  70. /*
  71.  * What facilities we export to the world
  72.  */
  73. int    xdopen(), xdstrategy();
  74. extern int    xxboot(), xxprobe();
  75. extern int    nullsys();
  76.  
  77. struct boottab xddriver = {
  78.     "xd",    xxprobe, xxboot, xdopen, nullsys, xdstrategy,
  79.     "\0", &xdinfo,
  80. }; 
  81.  
  82.  
  83. /*
  84.  * Open a xdlogics disk.
  85.  */
  86. xdopen(sip)
  87.     register struct saioreq *sip;
  88. {
  89.     register struct xdparam *xdp;
  90.     register struct xddevice *xdaddr;
  91.     register struct xdiopb *xd;
  92.     struct dk_label *label;
  93.     register int t;
  94.     u_short ppart;
  95. #ifndef BOOTBLOCK
  96.     int xdspin();
  97. #endif !BOOTBLOCK
  98.  
  99.     xdp = (struct xdparam *)sip->si_devdata;
  100.     xdaddr = (struct xddevice *)sip->si_devaddr;
  101.     xd = &((struct xddma *)sip->si_dmaaddr)->xdiopb;
  102.  
  103.     xdp->xd_unit = sip->si_unit & 0x03;
  104.     ppart = (sip->si_unit >> 2) & 1;
  105.  
  106.     /* reset controller */
  107.     xdaddr->xd_csr = XD_RST; 
  108.     DELAY(300);
  109.  
  110.     xdp->xd_boff  = 0;        /* Don't offset block numbers */
  111.     xdp->xd_nsect = 2;
  112.     xdp->xd_nhead = 2;
  113.     xdp->xd_ncyl = 2;
  114.     xdp->xd_bad.bt_mbz = -1;
  115.  
  116. #ifndef BOOTBLOCK
  117.     /*
  118.      * Wait for disk to spin up, if necessary.
  119.      */
  120.     if (!isspinning(xdspin, (char *)sip, 0))
  121.         return (-1);
  122. #endif !BOOTBLOCK
  123.  
  124.     label = (struct dk_label *)
  125.         ((struct xddma *)sip->si_dmaaddr)->xdblock;
  126.     label->dkl_magic = 0;
  127.     if (xdcmd(XD_READ, sip, 0, (char *)label, 1)) 
  128.         goto badopen;
  129.     if (chklabel(label)) 
  130.         goto badopen;
  131.     if (ppart != label->dkl_ppart)
  132.         goto badopen;
  133.     goto foundlabel;
  134.  
  135. badopen:
  136.     printf(msg_nolabel);
  137.     return (-1);
  138.  
  139. foundlabel:
  140.     xdp->xd_nhead = label->dkl_nhead;
  141.     xdp->xd_nsect = label->dkl_nsect;
  142.     xdp->xd_ncyl  = label->dkl_ncyl + label->dkl_acyl;
  143.     xdp->xd_boff  = label->dkl_map[sip->si_boff].dkl_cylno;
  144.     xdp->xd_nblk  = label->dkl_map[sip->si_boff].dkl_nblk;
  145.  
  146.     if (xdcmd(XD_WPAR, sip, 0, 0, 0))
  147.         printf("xd: init error %x\n", xd->xd_errno);
  148.     /*
  149.      * Fetch bad block info.
  150.      */
  151.     xdp->xd_badaddr = ((int)xdp->xd_ncyl * xdp->xd_nhead - 1)
  152.               * xdp->xd_nsect;
  153.     if (xdcmd(XD_READ, sip, xdp->xd_badaddr, (char *)&xdp->xd_bad, 1))
  154.         printf("xd: no bad block info\n");
  155.     return (0);
  156. }
  157.  
  158. xdstrategy(sip, rw)
  159.     struct saioreq *sip;
  160.     int rw;
  161. {
  162.     register int cmd = (rw == WRITE) ? XD_WRITE : XD_READ;
  163.     register int boff;
  164.     register struct xdparam *xdp = (struct xdparam *)sip->si_devdata;
  165.     register short nsect;
  166. #ifndef BOOTBLOCK
  167.     char *ma;
  168.     int i, bn;
  169. #endif BOOTBLOCK
  170.  
  171.     boff = CYL(xdp->xd_boff);
  172. #ifdef BOOTBLOCK
  173.     /* assert si_cc == DEV_BSIZE */
  174.     if (xdcmd(cmd, sip, sip->si_bn + boff, sip->si_ma, 1))
  175.         return (-1);
  176.     return (sip->si_cc);
  177. #else BOOTBLOCK
  178.     nsect = sip->si_cc / DEV_BSIZE;
  179.     if (sip->si_bn + nsect > xdp->xd_nblk)
  180.         nsect = xdp->xd_nblk - sip->si_bn;
  181.     if (nsect == 0)
  182.         return (0);
  183.     if (xdcmd(cmd, sip, sip->si_bn+boff, sip->si_ma, nsect) == 0)
  184.         return (nsect*DEV_BSIZE);
  185.     /*
  186.      * Large transfer failed, now do one at a time
  187.      */
  188.     bn = sip->si_bn + boff;
  189.     ma = sip->si_ma;
  190.     for (i = 0; i < nsect; i++) {
  191.         if (xdcmd(cmd, sip, bn, ma, 1))
  192.             return (-1);
  193.         bn++;
  194.         ma += DEV_BSIZE;
  195.     }
  196.     return (nsect*DEV_BSIZE);
  197. #endif    BOOTBLOCK
  198. }
  199.  
  200. #ifndef BOOTBLOCK
  201. /*
  202.  * This routine is called from isspinning() as the test condition.
  203.  */
  204. int
  205. xdspin(sip, dummy)
  206.     struct saioreq *sip;
  207.     int dummy;
  208. {
  209.     register struct xdparam *xdp = (struct xdparam *)sip->si_devdata;
  210.     register struct xdiopb *xd = &((struct xddma *)sip->si_dmaaddr)->xdiopb;
  211.  
  212.     (void) xdcmd(XD_RESTORE, sip, 0, (char *)0, 0);
  213.     return ((xd->xd_dstat & XD_READY) ? 1 : 0);
  214. }
  215. #endif !BOOTBLOCK
  216.  
  217. xdcmd(cmd, sip, bno, buf, nsect)
  218.     int cmd;
  219.     struct saioreq *sip;
  220.     register int bno;
  221.     char *buf;
  222.     int nsect;
  223. {
  224.     register int i, t;
  225.     register struct xdparam *xdp = (struct xdparam *)sip->si_devdata;
  226.     register struct xdiopb *xd = &((struct xddma *)sip->si_dmaaddr)->xdiopb;
  227.     register struct xddevice *xdaddr = (struct xddevice *)sip->si_devaddr;
  228.     register char *bp = ((struct xddma *)sip->si_dmaaddr)->xdblock;
  229.     unsigned short cylno, sect, head;
  230.     int error, errcnt = 0;
  231.     int timeout = 0;
  232.     int firstime = 1;
  233.  
  234.     cylno = bno / CYL(1);
  235.     sect = bno % xdp->xd_nsect;
  236.     head = (bno / xdp->xd_nsect) % xdp->xd_nhead;
  237.  
  238.     if (cmd == XD_WRITE && buf != bp)    /* Many just use common buf */
  239.         bcopy(buf, bp, nsect*DEV_BSIZE);
  240.  
  241. retry:
  242.     bzero((char *)xd, sizeof (struct xdiopb));
  243.     xd->xd_cmd = cmd >> 8;
  244.     switch (cmd) {
  245.         case XD_WPAR:
  246.             xd->xd_subfunc = XD_DRIVE;
  247.             xd->xd_drparam = 0;        
  248.             xd->xd_nsect = (short) ((xdp->xd_nsect - 1) << 8);
  249.             xd->xd_cylinder = xdp->xd_ncyl - 1;
  250.             xd->xd_head = xdp->xd_nhead - 1;
  251.             xd->xd_sector = xdp->xd_nsect - 1;
  252.             break;
  253.  
  254.         default:
  255.             xd->xd_subfunc = 0;
  256.             xd->xd_nsect = nsect;
  257.             xd->xd_cylinder = cylno;
  258.             xd->xd_head = head;
  259.             xd->xd_sector = sect;
  260.             xd->xd_bufaddr = (int) (MB_DMA_ADDR(bp));
  261.     }
  262.     xd->xd_unit = xdp->xd_unit & 3;
  263.     xd->xd_intpri = 0;            /* disable interrupt */
  264.     xd->xd_bufmod = XD_ADDRMOD24;        /* standard supervisory */
  265.  
  266.     t = (int) (MB_DMA_ADDR(xd));
  267.     xdaddr->xd_iopbaddr1 = (int) t;
  268.     xdaddr->xd_iopbaddr2 = (int) t >> 8;
  269.     xdaddr->xd_iopbaddr3 = (int) t >> 16;
  270.     xdaddr->xd_iopbaddr4 = (int) t >> 24;
  271.     xdaddr->xd_modifier = XD_ADDRMOD24;
  272.     xdaddr->xd_csr = XD_AIO;
  273.  
  274.     while (!(xdaddr->xd_csr & XD_RIO) && timeout < TIMEOUT)
  275.         timeout++;    
  276.     
  277.     if (timeout == TIMEOUT) {
  278.         /*
  279.          * kludge for the 751 prototype. this
  280.          * doesn't hurt in the normal case and we
  281.          * didn't wanted to risk another prom release.
  282.          * so here it is.
  283.          */
  284.         if (firstime && cmd == XD_RESTORE) {
  285.             xdaddr->xd_csr = XD_RST;
  286.             DELAY(300);
  287.             firstime = 0;
  288.             timeout = 0;
  289.             goto retry;
  290.         } 
  291.         printf("disk ctlr timeout cmd %x\n", cmd);
  292.         xdaddr->xd_csr = XD_RST;     /* reset the controller */
  293.         return(-1);
  294.     }
  295.  
  296.     if (xdaddr->xd_csr & XD_FERR) {
  297.         xdaddr->xd_csr = XD_RST;
  298.         DELAY(300);
  299.         xd->xd_iserr = 1;
  300.     }
  301.  
  302.     xdaddr->xd_csr = XD_CLRIO;    /* clear rio bit */
  303.     xdaddr->xd_csr = XD_CLRBS;    /* release register */
  304.  
  305.     if (xd->xd_iserr && xd->xd_errno != XDE_FECC) {
  306.         if (nsect != 1)        /* only try hard on single sectors */
  307.             return (-1);
  308.         error = xd->xd_errno;
  309.         if ((i = xdfwd(xdp, cylno, head, sect)) != 0)
  310.             return xdcmd(cmd, sip, i, buf, 1);
  311.         /* Attempt to reset the error condition */
  312.         if (cmd != XD_RESTORE) {
  313.             xdaddr->xd_csr = XD_RST; /* reset the controller */
  314.             DELAY(300);         /* and then the drive */
  315.             (void) xdcmd(XD_RESTORE, sip, 0, (char *)0, 1);
  316.         }
  317.         if (++errcnt < 5)
  318.             goto retry;
  319.         if (bno != 0)    /* drive type probe */
  320.             printf("xd: error %x bno %d\n", error, bno);
  321.         return (-1);            /* Error */
  322.     }
  323.  
  324.     if (cmd == XD_READ && buf != bp)    /* Many just use common buf */
  325.         bcopy(bp, buf, nsect*DEV_BSIZE);
  326.  
  327.     return (0);
  328. }
  329.  
  330. xdfwd(xdp, cn, tn, sn)
  331.     register struct xdparam *xdp;
  332.     int cn, tn, sn;
  333. {
  334.     register struct dkbad *bt = &xdp->xd_bad;
  335.     register int i;
  336.  
  337.     if (bt->bt_mbz != 0)    /* not initialized */
  338.         return (0);
  339.     for (i=0; i<126; i++)        /* FIXME constant */
  340.         if (bt->bt_bad[i].bt_cyl == cn &&
  341.             bt->bt_bad[i].bt_trksec == (tn<<8)+sn) {
  342.             return (xdp->xd_badaddr - i - 1);
  343.         }
  344.     return (0);
  345. }
  346. #endif M25
  347.